<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>目标选择器测试</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 20px;
            background-color: #f0f0f0;
        }
        .container {
            max-width: 800px;
            margin: 0 auto;
            background: white;
            padding: 20px;
            border-radius: 8px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
        }
        .test-section {
            margin: 20px 0;
            padding: 15px;
            border: 1px solid #ddd;
            border-radius: 5px;
        }
        .test-result {
            margin: 10px 0;
            padding: 10px;
            border-radius: 3px;
        }
        .success {
            background-color: #d4edda;
            color: #155724;
            border: 1px solid #c3e6cb;
        }
        .error {
            background-color: #f8d7da;
            color: #721c24;
            border: 1px solid #f5c6cb;
        }
        .info {
            background-color: #d1ecf1;
            color: #0c5460;
            border: 1px solid #bee5eb;
        }
        button {
            background-color: #007bff;
            color: white;
            border: none;
            padding: 10px 20px;
            border-radius: 5px;
            cursor: pointer;
            margin: 5px;
        }
        button:hover {
            background-color: #0056b3;
        }
        .entity-list {
            display: flex;
            flex-wrap: wrap;
            gap: 10px;
            margin: 10px 0;
        }
        .entity-item {
            background-color: #e9ecef;
            padding: 8px 12px;
            border-radius: 4px;
            font-size: 12px;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>智能对话目标选择系统测试</h1>
        <p>测试TargetSelector类的各项功能</p>

        <div class="test-section">
            <h3>测试场景设置</h3>
            <div id="scenario-info" class="info">
                <p>玩家位置: (0, 0, 0)</p>
                <p>检测范围: 10格</p>
            </div>
            <div class="entity-list" id="entity-list">
                <!-- 实体列表将在这里显示 -->
            </div>
            <button onclick="generateTestEntities()">生成测试实体</button>
            <button onclick="clearEntities()">清除实体</button>
        </div>

        <div class="test-section">
            <h3>目标选择测试</h3>
            <button onclick="testSingleTarget()">测试单个目标选择</button>
            <button onclick="testMultipleTargets()">测试多目标选择</button>
            <button onclick="testNoTargets()">测试无目标情况</button>
            <button onclick="testTargetPriority()">测试目标优先级</button>
            <div id="selection-results"></div>
        </div>

        <div class="test-section">
            <h3>对话状态测试</h3>
            <button onclick="testConversationState()">测试对话状态保持</button>
            <button onclick="testTargetSwitching()">测试目标切换</button>
            <button onclick="testRangeValidation()">测试范围验证</button>
            <div id="conversation-results"></div>
        </div>

        <div class="test-section">
            <h3>目标选择器状态</h3>
            <div id="selector-status" class="info">
                <!-- 状态信息将在这里显示 -->
            </div>
            <button onclick="updateStatus()">更新状态</button>
            <button onclick="resetSelector()">重置选择器</button>
        </div>
    </div>

    <script type="module">
        // 模拟实体类
        class MockEntity {
            constructor(id, type, position, isAlive = true) {
                this.id = id;
                this.type = type;
                this.position = position;
                this.alive = isAlive;
            }

            getId() { return this.id; }
            getType() { return this.type; }
            getPosition() { return { ...this.position }; }
            isAlive() { return this.alive; }
        }

        // 模拟EntityPersonas
        const mockPersonas = {
            'cow': { name: '奶牛', personality: '温和' },
            'pig': { name: '猪', personality: '贪吃' },
            'sheep': { name: '羊', personality: '温顺' },
            'zombie': { name: '僵尸', personality: '混乱' },
            'skeleton': { name: '骷髅', personality: '冷酷' }
        };

        window.getEntityPersona = function(type) {
            return mockPersonas[type] || null;
        };

        // 模拟TargetSelector类
        class TargetSelector {
            constructor(maxDetectionRange = 10) {
                this.currentTarget = null;
                this.maxDetectionRange = maxDetectionRange;
                this.targetSwitchCooldown = 1000;
                this.lastTargetSwitchTime = 0;
                this.conversationInProgress = false;
            }

            selectBestTarget(playerPosition, entities) {
                const validTargets = entities.filter(entity => this.isValidTarget(entity, playerPosition));

                if (validTargets.length === 0) {
                    if (this.currentTarget) {
                        this.currentTarget = null;
                        this.conversationInProgress = false;
                    }
                    return null;
                }

                if (validTargets.length === 1) {
                    const target = validTargets[0];
                    this.setCurrentTarget(target);
                    return target;
                }

                if (this.conversationInProgress && this.currentTarget && this.isValidTarget(this.currentTarget, playerPosition)) {
                    return this.currentTarget;
                }

                const closestTarget = this.findClosestTarget(playerPosition, validTargets);
                
                if (this.shouldSwitchTarget(closestTarget)) {
                    this.setCurrentTarget(closestTarget);
                    return closestTarget;
                }

                return this.currentTarget && this.isValidTarget(this.currentTarget, playerPosition) 
                    ? this.currentTarget 
                    : closestTarget;
            }

            calculateTargetPriority(entity, playerPosition) {
                let priority = 0;

                const distance = this.calculateDistance(playerPosition, entity.getPosition());
                const maxDistance = this.maxDetectionRange;
                const distanceFactor = Math.max(0, (maxDistance - distance) / maxDistance);
                priority += distanceFactor * 100;

                const typeBonus = this.getEntityTypeBonus(entity.getType());
                priority += typeBonus;

                if (this.currentTarget && entity.getId() === this.currentTarget.getId()) {
                    priority += 50;
                }

                if (entity.isAlive()) {
                    priority += 20;
                }

                return priority;
            }

            isValidTarget(entity, playerPosition) {
                if (!entity || !entity.isAlive()) {
                    return false;
                }

                const persona = window.getEntityPersona(entity.getType());
                if (!persona) {
                    return false;
                }

                if (playerPosition) {
                    const distance = this.calculateDistance(playerPosition, entity.getPosition());
                    if (distance > this.maxDetectionRange) {
                        return false;
                    }
                }

                return true;
            }

            switchTarget(newTarget) {
                const previousTarget = this.currentTarget;
                this.setCurrentTarget(newTarget);
                
                if (previousTarget && newTarget && previousTarget.getId() !== newTarget.getId()) {
                    this.conversationInProgress = false;
                }
            }

            getCurrentTarget() {
                return this.currentTarget;
            }

            setConversationInProgress(inProgress) {
                this.conversationInProgress = inProgress;
            }

            checkCurrentTargetValidity(playerPosition) {
                if (!this.currentTarget) {
                    return false;
                }

                if (!this.isValidTarget(this.currentTarget, playerPosition)) {
                    this.currentTarget = null;
                    this.conversationInProgress = false;
                    return false;
                }

                return true;
            }

            setDetectionRange(range) {
                this.maxDetectionRange = Math.max(1, range);
            }

            getDetectionRange() {
                return this.maxDetectionRange;
            }

            findClosestTarget(playerPosition, entities) {
                let closestEntity = entities[0];
                let closestDistance = this.calculateDistance(playerPosition, closestEntity.getPosition());

                for (let i = 1; i < entities.length; i++) {
                    const distance = this.calculateDistance(playerPosition, entities[i].getPosition());
                    if (distance < closestDistance) {
                        closestDistance = distance;
                        closestEntity = entities[i];
                    }
                }

                return closestEntity;
            }

            calculateDistance(pos1, pos2) {
                const dx = pos1.x - pos2.x;
                const dy = pos1.y - pos2.y;
                const dz = pos1.z - pos2.z;
                return Math.sqrt(dx * dx + dy * dy + dz * dz);
            }

            setCurrentTarget(target) {
                this.currentTarget = target;
                this.lastTargetSwitchTime = Date.now();
            }

            shouldSwitchTarget(newTarget) {
                if (!newTarget) {
                    return false;
                }

                if (!this.currentTarget) {
                    return true;
                }

                if (newTarget.getId() === this.currentTarget.getId()) {
                    return false;
                }

                const currentTime = Date.now();
                if (currentTime - this.lastTargetSwitchTime < this.targetSwitchCooldown) {
                    return false;
                }

                if (this.conversationInProgress) {
                    const currentDistance = this.calculateDistance(
                        this.currentTarget.getPosition(), 
                        newTarget.getPosition()
                    );
                    return currentDistance > 2;
                }

                return true;
            }

            getEntityTypeBonus(entityType) {
                const bonusMap = {
                    'cow': 10,
                    'pig': 8,
                    'sheep': 12,
                    'zombie': 5,
                    'skeleton': 3
                };

                return bonusMap[entityType] || 0;
            }

            getValidTargetsInRange(playerPosition, entities) {
                return entities.filter(entity => this.isValidTarget(entity, playerPosition));
            }

            reset() {
                this.currentTarget = null;
                this.conversationInProgress = false;
                this.lastTargetSwitchTime = 0;
            }

            getStatus() {
                return {
                    currentTarget: this.currentTarget,
                    conversationInProgress: this.conversationInProgress,
                    detectionRange: this.maxDetectionRange,
                    lastSwitchTime: this.lastTargetSwitchTime
                };
            }
        }

        // 全局变量
        let targetSelector = new TargetSelector(10);
        let testEntities = [];
        const playerPosition = { x: 0, y: 0, z: 0 };

        // 测试函数
        window.generateTestEntities = function() {
            testEntities = [
                new MockEntity('cow1', 'cow', { x: 3, y: 0, z: 2 }),
                new MockEntity('pig1', 'pig', { x: -2, y: 0, z: 4 }),
                new MockEntity('sheep1', 'sheep', { x: 1, y: 0, z: -3 }),
                new MockEntity('zombie1', 'zombie', { x: 8, y: 0, z: 1 }),
                new MockEntity('skeleton1', 'skeleton', { x: -5, y: 0, z: -2 }),
                new MockEntity('cow2', 'cow', { x: 15, y: 0, z: 0 }, true), // 超出范围
                new MockEntity('pig2', 'pig', { x: 0, y: 0, z: 0 }, false) // 死亡状态
            ];
            updateEntityList();
            addResult('selection-results', '已生成测试实体', 'info');
        };

        window.clearEntities = function() {
            testEntities = [];
            updateEntityList();
            addResult('selection-results', '已清除所有实体', 'info');
        };

        window.testSingleTarget = function() {
            // 只保留一个有效目标
            const singleEntity = [new MockEntity('cow1', 'cow', { x: 3, y: 0, z: 2 })];
            const target = targetSelector.selectBestTarget(playerPosition, singleEntity);
            
            if (target && target.getId() === 'cow1') {
                addResult('selection-results', '✓ 单个目标选择测试通过', 'success');
            } else {
                addResult('selection-results', '✗ 单个目标选择测试失败', 'error');
            }
        };

        window.testMultipleTargets = function() {
            if (testEntities.length === 0) {
                generateTestEntities();
            }
            
            const target = targetSelector.selectBestTarget(playerPosition, testEntities);
            
            if (target) {
                const distance = targetSelector.calculateDistance(playerPosition, target.getPosition());
                addResult('selection-results', `✓ 多目标选择测试通过 - 选中: ${target.getType()}(${target.getId()}), 距离: ${distance.toFixed(2)}`, 'success');
            } else {
                addResult('selection-results', '✗ 多目标选择测试失败 - 未选中任何目标', 'error');
            }
        };

        window.testNoTargets = function() {
            const target = targetSelector.selectBestTarget(playerPosition, []);
            
            if (target === null) {
                addResult('selection-results', '✓ 无目标测试通过 - 正确返回null', 'success');
            } else {
                addResult('selection-results', '✗ 无目标测试失败 - 应该返回null', 'error');
            }
        };

        window.testTargetPriority = function() {
            if (testEntities.length === 0) {
                generateTestEntities();
            }
            
            const validTargets = targetSelector.getValidTargetsInRange(playerPosition, testEntities);
            const priorities = validTargets.map(entity => ({
                entity,
                priority: targetSelector.calculateTargetPriority(entity, playerPosition)
            })).sort((a, b) => b.priority - a.priority);
            
            let resultText = '目标优先级排序:\n';
            priorities.forEach((item, index) => {
                resultText += `${index + 1}. ${item.entity.getType()}(${item.entity.getId()}) - 优先级: ${item.priority.toFixed(2)}\n`;
            });
            
            addResult('selection-results', resultText, 'info');
        };

        window.testConversationState = function() {
            if (testEntities.length === 0) {
                generateTestEntities();
            }
            
            // 开始对话
            const target = targetSelector.selectBestTarget(playerPosition, testEntities);
            targetSelector.setConversationInProgress(true);
            
            // 再次选择，应该保持当前目标
            const sameTarget = targetSelector.selectBestTarget(playerPosition, testEntities);
            
            if (target && sameTarget && target.getId() === sameTarget.getId()) {
                addResult('conversation-results', '✓ 对话状态保持测试通过', 'success');
            } else {
                addResult('conversation-results', '✗ 对话状态保持测试失败', 'error');
            }
        };

        window.testTargetSwitching = function() {
            if (testEntities.length === 0) {
                generateTestEntities();
            }
            
            const target1 = targetSelector.selectBestTarget(playerPosition, testEntities);
            const newTarget = new MockEntity('new1', 'cow', { x: 0.5, y: 0, z: 0.5 }); // 非常近的目标
            
            targetSelector.switchTarget(newTarget);
            const currentTarget = targetSelector.getCurrentTarget();
            
            if (currentTarget && currentTarget.getId() === 'new1') {
                addResult('conversation-results', '✓ 目标切换测试通过', 'success');
            } else {
                addResult('conversation-results', '✗ 目标切换测试失败', 'error');
            }
        };

        window.testRangeValidation = function() {
            const nearEntity = new MockEntity('near1', 'cow', { x: 2, y: 0, z: 2 });
            const farEntity = new MockEntity('far1', 'pig', { x: 20, y: 0, z: 20 });
            
            const nearValid = targetSelector.isValidTarget(nearEntity, playerPosition);
            const farValid = targetSelector.isValidTarget(farEntity, playerPosition);
            
            if (nearValid && !farValid) {
                addResult('conversation-results', '✓ 范围验证测试通过', 'success');
            } else {
                addResult('conversation-results', `✗ 范围验证测试失败 - 近距离:${nearValid}, 远距离:${farValid}`, 'error');
            }
        };

        window.updateStatus = function() {
            const status = targetSelector.getStatus();
            const statusDiv = document.getElementById('selector-status');
            
            statusDiv.innerHTML = `
                <p><strong>当前目标:</strong> ${status.currentTarget ? `${status.currentTarget.getType()}(${status.currentTarget.getId()})` : '无'}</p>
                <p><strong>对话进行中:</strong> ${status.conversationInProgress ? '是' : '否'}</p>
                <p><strong>检测范围:</strong> ${status.detectionRange}格</p>
                <p><strong>上次切换时间:</strong> ${status.lastSwitchTime ? new Date(status.lastSwitchTime).toLocaleTimeString() : '从未切换'}</p>
            `;
        };

        window.resetSelector = function() {
            targetSelector.reset();
            updateStatus();
            addResult('conversation-results', '目标选择器已重置', 'info');
        };

        function updateEntityList() {
            const listDiv = document.getElementById('entity-list');
            listDiv.innerHTML = '';
            
            testEntities.forEach(entity => {
                const distance = targetSelector.calculateDistance(playerPosition, entity.getPosition());
                const isValid = targetSelector.isValidTarget(entity, playerPosition);
                
                const entityDiv = document.createElement('div');
                entityDiv.className = 'entity-item';
                entityDiv.style.backgroundColor = isValid ? '#d4edda' : '#f8d7da';
                entityDiv.innerHTML = `
                    ${entity.getType()}(${entity.getId()})<br>
                    位置: (${entity.getPosition().x}, ${entity.getPosition().y}, ${entity.getPosition().z})<br>
                    距离: ${distance.toFixed(2)}格<br>
                    状态: ${entity.isAlive() ? '存活' : '死亡'}<br>
                    有效: ${isValid ? '是' : '否'}
                `;
                listDiv.appendChild(entityDiv);
            });
        }

        function addResult(containerId, message, type) {
            const container = document.getElementById(containerId);
            const resultDiv = document.createElement('div');
            resultDiv.className = `test-result ${type}`;
            resultDiv.innerHTML = message.replace(/\n/g, '<br>');
            container.appendChild(resultDiv);
            
            // 限制结果数量
            const results = container.querySelectorAll('.test-result');
            if (results.length > 10) {
                results[0].remove();
            }
        }

        // 初始化
        updateStatus();
        generateTestEntities();
    </script>
</body>
</html>